package dyyx;

import java.lang.management.BufferPoolMXBean;
import java.lang.management.ClassLoadingMXBean;
import java.lang.management.GarbageCollectorMXBean;
import java.lang.management.ManagementFactory;
import java.lang.management.MemoryMXBean;
import java.lang.management.MemoryPoolMXBean;
import java.lang.management.MemoryUsage;
import java.lang.management.OperatingSystemMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.ThreadMXBean;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

public abstract class JvmUtil {

    private static final OperatingSystemMXBean op = ManagementFactory.getOperatingSystemMXBean();
    private static final ThreadMXBean tmb = ManagementFactory.getThreadMXBean();
    private static final ClassLoadingMXBean clmb = ManagementFactory.getClassLoadingMXBean();
    private static final List<GarbageCollectorMXBean> gcmbs = ManagementFactory.getGarbageCollectorMXBeans();
    private static final List<MemoryPoolMXBean> mps = ManagementFactory.getMemoryPoolMXBeans();
    private static final Runtime rt = Runtime.getRuntime();

    private static final MemoryMXBean memoryBean = ManagementFactory.getMemoryMXBean();

    private static final List<BufferPoolMXBean> bufpools = ManagementFactory.getPlatformMXBeans(BufferPoolMXBean.class);

    // private static final sun.management.HotspotRuntimeMBean hotspotRuntimeMBean = sun.management.ManagementFactoryHelper
    //        .getHotspotRuntimeMBean();

    public static long maxMemory() {
        return rt.maxMemory();
    }

    public static long heapUsed() {
        MemoryUsage mu = memoryBean.getHeapMemoryUsage();
        return mu.getUsed();
    }

    public static long heapUsedMb() {
        MemoryUsage mu = memoryBean.getHeapMemoryUsage();
        return mu.getUsed() / (1024L * 1024L);
    }

    public static long heapUsedGb() {
        MemoryUsage mu = memoryBean.getHeapMemoryUsage();
        return mu.getUsed() / (1024L * 1024L * 1024L);
    }

    public static Map<String, String> getStatus() {

        Map<String, String> map = new LinkedHashMap<String, String>();

        map.put("maxMemory", rt.maxMemory() + "");
        map.put("totalMemory", rt.totalMemory() + "");
        map.put("freeMemory", rt.freeMemory() + "");

        map.put("lastMinuteLoad", op.getSystemLoadAverage() + "");

        map.put("availableProcessors", rt.availableProcessors() + "");

        map.put("peakThreadCount", tmb.getPeakThreadCount() + "");
        map.put("threadCount", tmb.getThreadCount() + "");
        map.put("totalStartedThreadCount", tmb.getTotalStartedThreadCount() + "");
        map.put("daemonThreadCount", tmb.getDaemonThreadCount() + "");

        map.put("totalLoadedClassCount", clmb.getTotalLoadedClassCount() + "");
        map.put("loadedClassCount", clmb.getLoadedClassCount() + "");
        map.put("unloadedClassCount", clmb.getUnloadedClassCount() + "");

        try {
            MemoryUsage mu = memoryBean.getHeapMemoryUsage();
            map.put("heapUsed", mu.getUsed() + "");
            mu = memoryBean.getNonHeapMemoryUsage();
            map.put("nonHeapUsed", mu.getUsed() + "");

        } catch (Throwable e) {

        }

        if (gcmbs != null) {
            int num = gcmbs.size();

            for (int i = 0; i < num; i++) {
                GarbageCollectorMXBean mb = gcmbs.get(i);
                String key = "gc" + i;
                StringBuilder sb = new StringBuilder();
                sb.append("name=" + mb.getName());
                sb.append(",count=" + mb.getCollectionCount());
                sb.append(",time=" + mb.getCollectionTime());
                map.put(key, sb.toString());
            }
        }

        if (mps != null) {
            int num = mps.size();

            for (int i = 0; i < num; i++) {
                MemoryPoolMXBean mb = mps.get(i);
                String key = "mempool" + i;
                StringBuilder sb = new StringBuilder();
                sb.append("name=" + mb.getName());
                sb.append(",type=" + mb.getType());
                sb.append(",usage=" + mb.getUsage());
                sb.append(",collectionUsage=" + mb.getCollectionUsage());

                map.put(key, sb.toString());
            }

        }

        if (bufpools != null) {
            int num = bufpools.size();

            for (int i = 0; i < num; i++) {
                BufferPoolMXBean mb = bufpools.get(i);
                String key = "bufpool" + i;
                StringBuilder sb = new StringBuilder();
                sb.append("name=" + mb.getName());
                sb.append(",count=" + mb.getCount());
                sb.append(",memoryUsed=" + mb.getMemoryUsed());
                sb.append(",totalCapacity=" + mb.getTotalCapacity());

                map.put(key, sb.toString());
            }

        }

        return map;
    }

    public static ThreadInfo getThreadInfo(long id, int maxDepth) {
        return tmb.getThreadInfo(id, maxDepth);
    }

    public static ThreadInfo[] getThreadInfos(long[] ids, int maxDepth) {
        return tmb.getThreadInfo(ids, maxDepth);
    }

    public static ThreadInfo getThreadInfo(long id) {
        return tmb.getThreadInfo(id, 9);
    }

    public static ThreadInfo[] getThreadInfos(long[] ids) {
        return tmb.getThreadInfo(ids, 9);
    }

}
